/**************************
* @Summary
* @Author 20009200303 赵传博
* @Date 2022/4/27
*****************************/

#include "Parser.h"

ExprNode *Parser::expr(bool get) {
    ExprNode* left;
    ExprNode* right;
    left = term(get);       //得到+-操作的左子树

    if(!left) return nullptr;

    for(;;){
        switch (lexer->getcurrentToken()) {
            case PLUS:
                right = term(true);

                if(!right){
                    delete left;
                    return nullptr;
                }

                left = new ExprNode(PLUS, left, right);
                break;
            case MINUS:
                right = term(true);

                if(!right){
                    delete left;
                    return nullptr;
                }

                left = new ExprNode(MINUS, left, right);
            default:
                return left;

        }
    }

}

ExprNode *Parser::term(bool get) {
    ExprNode* left = prim(get);
    ExprNode* right;
    for(;;){
        switch (lexer->getcurrentToken()) {
            case MUL:
                right = prim(true);

                if(!right){
                    delete left;
                    return nullptr;
                }

                left = new ExprNode(MUL, left, right);
                return left;

            case DIV:
                right = prim(true);

                if(!right){
                    delete left;
                    return nullptr;
                }else if(right->getValue() == 0){
                    cerr << "divide by 0" << endl;
                    return nullptr;
                }

                left = new ExprNode(DIV, left, right);
                return left;

            default: return left;
        }
    }
}

ExprNode *Parser::prim(bool get) {
    if(get) lexer->get_token();
    switch(lexer->getcurrentToken()){
        case NUMBER:{
            double v = lexer->getNumber_value();
            auto* number = new ExprNode(NUMBER, nullptr, nullptr, v);
            lexer->setNumberValue(0);
            lexer->get_token();
            return number;
        }
        case NAME:{
            auto iter = lexer->getTable().find(lexer->getString_value());
            //如果在表中没有找到变量
            ExprNode* number_of_val = nullptr;
            if(iter == lexer->getTable().end()){
                number_of_val = new ExprNode(NAME, nullptr, nullptr, 0);
                if(lexer->get_token() == ASSIGN){
                    number_of_val = expr(true);
                    lexer->getTable().insert(pair<string, double>(lexer->getString_value(), number_of_val->getValue()));
                    number_of_val->setAssignEnd();
                    return number_of_val;
                }else{

                }
            }else{
                double num = lexer->getTable().at(lexer->getString_value());
                number_of_val = new ExprNode(NAME, nullptr, nullptr, num);
                lexer->setNumberValue(0);
                lexer->get_token();
                return number_of_val;
            }
            //double v = lexer->getTable().at(lexer->getString_value());


            return number_of_val;
        }
        case MINUS:{
            auto* number = new ExprNode(NUMBER, nullptr, nullptr, -prim(true)->getValue());
            return number;
        }
        case LP:{
            ExprNode* e = expr(true);
            if(lexer->getcurrentToken() != RP) return nullptr;
            lexer->get_token();
            return e;
        }
        default: return nullptr;
    }
}

ExprNode *Parser::parse_expr(const char *strExpr) {
    exprText = strExpr;
    //lexer = Lexer::getInstance(exprText.c_str());
    Token_type tok = lexer->get_token();
    if(tok == PRINT || tok == END) return nullptr;
    ExprNode* root = expr(false);
    lexer->clear();
    return root;
}

Parser::~Parser() {
    delete lexer;
}

Parser::Parser() {
    lexer = Lexer::getInstance(exprText.c_str());
}

//这里和Lexer的报错Undefined..同理
Parser* Parser::parserInstance = nullptr;
Parser *Parser::getInstance() {
    if(!parserInstance){
        parserInstance = new Parser();
    }
    return parserInstance;
}


